package com.example.literj.kt.internal.operators.observable

import com.example.literj.kt.core.Observer
import com.example.literj.kt.internal.operators.QueueDisposable
import java.util.concurrent.atomic.AtomicInteger

class ObservableScalarXMap {
    class ScalarDisposable<T>(private val observer: Observer<T>, val value: T) : AtomicInteger(),
        QueueDisposable<T>, Runnable {
        override fun offer(value: T): Boolean {
            throw UnsupportedOperationException("Should not be called!")
        }

        override fun offer(v1: T, v2: T): Boolean {
            throw UnsupportedOperationException("Should not be called!")
        }

        override fun poll(): T? {
            if (get() == FUSED) {
                lazySet(ON_COMPLETE)
                return value
            }
            return null
        }

        override fun isEmpty(): Boolean {
            return get() != FUSED
        }

        override fun clear() {
            lazySet(ON_COMPLETE)
        }

        override fun dispose() {
            set(ON_COMPLETE)
        }

        override fun isDisposed()  = get() == ON_COMPLETE

        override fun requestFusion(mode: Int): Int {
            if ((mode and SYNC) != 0) {
                lazySet(FUSED)
                return SYNC
            }
            return NONE
        }

        override fun run() {
            if (get() == START && compareAndSet(START, ON_NEXT)) {
                observer.onNext(value)
                if (get() == ON_NEXT) {
                    lazySet(ON_COMPLETE)
                    observer.onComplete()
                }
            }
        }

        companion object {
            const val START = 0
            const val FUSED = 1
            const val ON_NEXT = 2
            const val ON_COMPLETE = 3
        }

        override fun toByte() = get().toByte()

        override fun toChar() = get().toChar()

        override fun toShort() = get().toShort()
    }
}